package io.gitee.macxiang.utils;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;

import org.apache.tomcat.util.http.fileupload.ByteArrayOutputStream;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;

import io.gitee.macxiang.sql.SnowflakeIdWorker;
import jakarta.servlet.http.HttpServletRequest;

/** 各种数据处理 */
public class Datas extends Files {
  public static final String[] DIGITS = { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" };
  public static final String[] UNITS = { "十", "百", "千", "万", "十", "百", "千", "亿", "十", "百", "千" };
  public static final SnowflakeIdWorker id19 = new SnowflakeIdWorker();

  /** 清理控制台(开发时) */
  public static void clear() {
    if ("dev".equals(System.getProperty("env"))) {
      System.out.print("\033[H\033[2J");
      System.out.flush();
    }
  }

  /**清理控制台(开发时)
   * @param p 清理时需要打印的内容
   */
  public static void clear(Object... p) {
    if ("dev".equals(System.getProperty("env"))) {
      System.out.print("\033[H\033[2J");
      System.out.flush();
      if (p.length > 0) {
        String o = "";
        for (Object object : p) {
          o += ", " + object.toString();
        }
        System.out.println(o.substring(2) + "\n");
      }
    }
  }

  /** 支持多参数的打印 */
  public static void print(Object... param) {
    List<String> a = new ArrayList<>();
    for (Object o : param) {
      a.add(o instanceof String || o instanceof Number ? (o.toString())
          : (String.format("%s: %s", o == null ? "null" : o.getClass().getName(), toJString(o))));
    }
    System.out.println(a.size() > 0 ? String.join(", ", a) : null);
  }

  /** 结束本程序 System.exit(0); */
  public static void exit() {
    System.exit(0);
  }

  /** 结束本程序,接受参数打印
   * @param param   想要打印的参数
   */
  public static void exit(Object... param) {
    String pString = "";
    for (Object o : param) {
      pString += " " + toJString(o);
    }
    System.out.println(pString.length() > 0 ? pString.substring(1) : null);
    System.exit(0);
  }

  /**获取字符串域名部分
   * @param url               要获取的的url 例如:https://www.qq.com/xxx?xxx=xxx
   * @return                  域名 www.qq.com
   */
  public static String toDomain(String url) {
    if (!isEmpty(url)) {
      String domainPattern = "^(?:https?://)?([^:/]+)";
      Pattern pattern = Pattern.compile(domainPattern);
      Matcher matcher = pattern.matcher(url);
      if (matcher.find()) {
        return matcher.group(1);
      }
      url = null;
    }
    return url;
  }

  /** 截取字符串固定字节
   * @param str               要截取的字符串
   * @param maxLength         要截取的长度
   * @return                  截取后的字符串
   */
  public static String trimToByteLength(String str, int maxLength) {
    if (str == null || str.isEmpty() || maxLength <= 0) {
      return "";
    }
    str = Pattern.compile("[^\\p{L}\\p{N}\\p{P}]").matcher(str).replaceAll(""); // 去除所有表情,防止微信搞事情
    byte[] bytes = str.getBytes(java.nio.charset.StandardCharsets.UTF_8);
    if (bytes.length <= maxLength) {
      return str;
    }

    // 反向查找最后一个完整的字符边界
    int lastValidIndex = -1;
    for (int i = maxLength - 1; i >= 0; i--) {
      if ((bytes[i] & 0xC0) != 0x80) {
        lastValidIndex = i;
        break;
      }
    }

    if (lastValidIndex == -1) {
      return ""; // 如果找不到有效的边界，返回空字符串
    }

    return new String(bytes, 0, lastValidIndex + 1, java.nio.charset.StandardCharsets.UTF_8);
  }

  /**取字符串30个字节,并在末尾添加...
   * @param str 要截取的字符串
   * @return 最大30字节的字符串
   */
  public static String trim30(String str) {
    return strLen(str) > 30
        ? String.format("%s...", trimToByteLength(str, 27))
        : str;
  }

  /**取字符串字节长度
   * @param str               要取长度的字符串
   * @return                  字节长度
   */
  public static int strLen(String str) {
    return str == null ? 0 : str.getBytes(java.nio.charset.StandardCharsets.UTF_8).length;
  }

  /**将参数url格式化成完整的URL,如果参数只是一个相对路径/path1/path2 会拼接域名
   * @param url     待拼接的域名
   * @param domain  默认域名; 如果此值为空 则 设定默认值为 /
   * @return        拼接好的域名,如果传入的url中有http开头.则保持不变;
   */
  public static String formatUrl(String url, String domain) {
    if (url == null) {
      url = "";
    }
    if (isEmpty(domain)) {
      domain = "/";
    } else if (domain.indexOf(':') < 0 && domain.indexOf('.') >= 0) {
      domain = "https://" + domain;
    }
    if (url.indexOf('/') == 0) {
      url = String.format("%s%s", domain, url);
    } else if (url.indexOf("http") != 0) {
      url = String.format("%s/%s", domain, url);
    }

    return url;
  }

  /**获取Exception错误信息的文本
   * @param e 报错内容
   * @return  错误文本
   */
  public static String errString(Exception e) {
    // StackTraceElement[] st = e.getStackTrace();
    // if (st.length > 0) {
    // s += " 文件定位: " + st[0].getFileName() + ":" + st[0].getLineNumber();
    // }

    String s = null;
    s = e.getMessage();
    if (e instanceof InvocationTargetException) {
      s = ((InvocationTargetException) e).getTargetException().getMessage();
    }

    return s;
  }

  /**克隆一个数据结构(简单的通过json进行克隆)
   * @param <T>   任意类型
   * @param v     要克隆的数据
   * @param clazz 数据类型
   * @return      克隆好的数据
   */
  public static <T> T clone(T v, Class<T> clazz) {
    return JSON.parseObject(JSON.toJSONString(v), clazz);
  }

  /** 是否包含非ASCII字符
   * @param str   字符串
   * @return      是否包含非ASCII字符
   */
  public static boolean containsNonAscii(String str) {
    return str != null && str.matches("(?s).*[\\u0080-\\uFFFF].*");
  }

  /** 数字转汉字
   * @param number 数字
   * @return      汉字表示的数字,例如 一万三千
   */
  public static String numberToChinese(int number) {
    String ret = "", str = String.valueOf(number);
    int n = str.length();
    for (int i = 0; i < n; i++) {
      int num = str.charAt(i) - '0';
      if (i != n - 1 && num != 0) {
        ret += DIGITS[num] + UNITS[n - 2 - i];
      } else {
        ret += DIGITS[num];
      }
    }
    return ret.replaceAll("^一十", "十").replaceAll("零+$", "").replaceAll("零+", "零");
  }

  /** 查询到返回下标,否则返回-1
   * @param arr 待查询数组
   * @param item 查询项
   * @return 查询结果下标,未找到返回-1
   */
  public static int includes(String[] arr, String item) {
    if (arr.length > 0 && item != null) {
      for (int i = 0; i < arr.length; i++) {
        if (item.equals(arr[i])) {
          return i;
        }
      }
    }
    return -1;
  }

  /** 字符串是否为空
   * @param str 要判断的字符串
   * @return 当str为null或""时返回true,否则返回false
   */
  public static boolean isEmpty(String str) {
    return str == null || str.isEmpty();
  }

  /** 获取一个随机ID
   * @return  返回一个19位随机ID
   */
  public static long getId() {
    return id19.idLong();
  }

  /** 获取一个19位长度的id,但是不准确
   * @return 19位长度的id,临时用可以,但是不准确
   */
  public static String sGetId() {
    return String.valueOf(getId());
  }

  /** 取UUID
   * @return UUID
   */
  public static String getUUID() {
    return getUUID(false);
  }

  /**取UUID
   * @param simple 是否去除符号-
   * @return UUID
   */
  public static String getUUID(boolean simple) {
    ThreadLocalRandom random = ThreadLocalRandom.current();
    String ret = (new UUID(random.nextLong(), random.nextLong())).toString();
    return simple ? ret.replace("-", "") : ret;
  }

  /** 获取一个36位的uuid
   * @return 36位uuid
   */
  public static String sGetId36() {
    return id19.id36();
  }

  /** 获取一个36位的uuid去除符号-
   * @return 36位的uuid去除符号-
   */
  public static String sGetId32() {
    return id19.id32();
  }

  /** 获取一个40位长度的随机数
   * @return  40位长度的随机数
   */
  public static String sGetId40() {
    return id19.id40();
  }

  /** 将任意数据变成JSONObject
   * @param p     任意数据
   * @return      JSONObject对象
   */
  public static JSONObject toJsonObject(Object p) {
    if (p != null) {
      try {
        return JSONObject.parseObject((String) p);
      } catch (Exception e) {
        try {
          return JSON.parseObject(toJString(p));
        } catch (Exception ee) {
        }
      }
    }
    return null;
  }

  /** 将数据转化成json字符串
   * @param p 数据
   * @return json字符串
   */
  public static String toJString(Object p) {
    return p != null
        ? JSON.toJSONString(p, JSONWriter.Feature.WriteLongAsString, JSONWriter.Feature.WriteBigDecimalAsPlain,
            JSONWriter.Feature.WriteByteArrayAsBase64, JSONWriter.Feature.WriteNullListAsEmpty)
        : "";
  }

  /**将JSONObject转化成java数据
   * @param <T>   数据类型
   * @param p     待转化的数据
   * @param clazz 数据类型
   * @return      转化好的数据
   */
  public static <T> T toJavaObject(JSONObject p, Class<T> clazz) {
    try {
      return p.toJavaObject(clazz, JSONReader.Feature.Base64StringAsByteArray);
    } catch (Exception e) {
      JSONObject t = p.getJSONObject("permission");
      int l = p.getSize("permission");
      byte[] b = new byte[l];
      for (int i = 0; i < l; i++) {
        b[i] = t.getByteValue(String.valueOf(i));
      }
      p.remove("permission");
      p.put("permission", b);
      return p.toJavaObject(clazz);
    }
  }

  /** 将字json符串转换成实体类
   * @param <T>     实体类泛型
   * @param str     json字符串
   * @param clazz   实体类类型
   * @return        实体类
   */
  @SuppressWarnings("unchecked")
  public static <T> T parseJavaObject(String str, Class<T> clazz) {
    Object ret = null;
    if (clazz.isArray()) {
      Class<?> c = clazz.getComponentType();
      ret = Byte.class.isAssignableFrom(c) || byte.class == c
          ? Base64.getDecoder().decode(str)
          : JSONArray.parseArray(str, clazz, JSONReader.Feature.Base64StringAsByteArray);
    } else {
      try {
        ret = JSONObject.parseObject(str, clazz, JSONReader.Feature.Base64StringAsByteArray);
        if (ret == null && String.class.isAssignableFrom(clazz)) {
          ret = str;
        }
      } catch (Exception e1) {
        if (String.class.isAssignableFrom(clazz)) {
          ret = str;
        } else {
          try { // 可能是基本类型数据
            Class<?> dynamicClass = DynamicClass.createDynamicClass(clazz);
            ret = JSONObject.parseObject(String.format("{\"key\":%s}", str),
                dynamicClass,
                JSONReader.Feature.Base64StringAsByteArray);
            ret = dynamicClass.getDeclaredField("key").get(ret);
          } catch (Exception e) {
            ret = null;
          }
        }
      }
      if (ret == null && clazz.isPrimitive()) {
        ret = clazz == boolean.class ? false : 0;
      }
    }
    return (T) ret;
  }

  /** 将json转化成JSONArray
   * @param param   json字符串
   * @return        JSONArray
   */
  public static JSONArray toArray(String param) {
    return JSON.parseArray(param, JSONReader.Feature.Base64StringAsByteArray);
  }

  /** 将json转化成List
   * @param <T>   列表数据的类型
   * @param p     json字符串
   * @param clazz 列表数据的类型
   * @return      列表数据
   */
  public static <T> List<T> toArray(String p, Class<T> clazz) {
    return JSON.parseArray(p, clazz, JSONReader.Feature.Base64StringAsByteArray);
  }

  /**查找数组下标
   * @param <T>       数组类型
   * @param list      要查找的数组
   * @param predicate 元素遍历时的判断方法
   * @return          下标;未找到返回-1
   */
  public static <T> int arrFindIndex(List<T> list, java.util.function.Predicate<T> predicate) {
    return list.stream().filter(predicate).mapToInt(i -> list.indexOf(i)).findFirst().orElse(-1);
  }

  /**查找字符串数组下标
   * @param list      要查找的数组
   * @param p         要查找的元素
   * @return          下标;未找到返回-1
   */
  public static int arrFindIndex(List<String> list, String p) {
    if (p == null || list == null) {
      return -1;
    }
    return arrFindIndex(list, e -> p.equals(e));
  }

  /**查找字符串数组下标
   * @param list      要查找的数组
   * @param str       要查找的元素
   * @return          下标;未找到返回-1
   */
  public static int arrFindIndex(String[] list, String str) {
    for (int i = 0; i < list.length; i++) {
      if (str.equals(list[i])) {
        return i;
      }
    }
    return -1;
  }

  /**类似于JavaScript的find方法，返回列表中第一个满足predicate条件的元素。
   * 如果没有元素满足条件，则返回Optional.empty()。
   * @param <T>       列表元素类型
   * @param list      要搜索的列表
   * @param predicate 用于测试每个元素是否满足条件的Predicate
   * @return 第一个满足条件的元素，如果没有则为Optional.empty()
   */
  public static <T> T arrFind(List<T> list, java.util.function.Predicate<T> predicate) {
    return list.stream().filter(predicate).findFirst().orElse(null);
  }

  /** 是否数字
   * @param str     要判断的字符串
   * @return        是否数字
   */
  public static boolean isNumeric(String str) {
    if (str == null) {
      return false;
    }
    // 正则表达式匹配负数、正数和浮点数
    String regex = "^[\\-]?[0-9]+\\.?[0-9]+$";
    Pattern pattern = Pattern.compile(regex);
    Matcher matcher = pattern.matcher(str);
    return matcher.matches();
  }

  /**取字符出现的次数
   * @param str 待计算字符字数的字符串
   * @param c   待计算的字符
   * @return    字符出现的次数
   */
  public static int countStrC(String str, char c) {
    int count = 0;
    if (str != null) {
      for (int i = 0; i < str.length(); i++) {
        if (str.charAt(i) == c) {
          count++;
        }
      }
    }
    return count;
  }

  /**设置字符串中某个位置的字符
   * @param str   待设置的字符串
   * @param index 位置
   * @param c     欲设置的字符
   * @return      设置好的字符串
   */
  public static String setStrChar(String str, int index, char c) {
    StringBuilder sb = new StringBuilder(str);
    sb.setCharAt(index, c);
    return sb.toString();
  }

  /**循环生成固定字符串的字符串
   * @param len 欲生成的字符串长度
   * @param str 用作拼接的字符串
   * @return    生成好的字符串
   */
  public static String genStr(int len, String str) {
    if (str == null) {
      str = "0";
    }
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < len; i++) {
      sb.append(str);
    }
    return sb.toString();
  }

  /**安全的获取数组下标的元素,超出下标返回null
   * @param <T>   数据类型
   * @param list  要获取数据的数组
   * @param index 下标;可以使 int/str
   * @return      成功返回元素,失败返回null
   */
  public static <T> T listGet(List<T> list, int index) {
    try {
      return list.get(index);
    } catch (Exception e) {
    }
    return null;
  }

  /**安全的获取数组下标的元素,超出下标返回null
   * @param <T>   数据类型
   * @param list  要获取数据的数组
   * @param index 下标;可以使 int/str
   * @return      成功返回元素,失败返回null
   */
  public static <T> T listGet(List<T> list, String index) {
    return listGet(list, Integer.valueOf(index));
  }

  /**查找字符串数组下标
   * @param list    待查找的数组
   * @param param   欲查找的元素
   * @return        下标.未找到返回-1
   */
  public static int listIndexOf(List<String> list, String param) {
    if (list != null) {
      int l = list.size();
      if (param == null) {
        for (int i = 0; i < l; i++) {
          if (list.get(i) == null) {
            return i;
          }
        }
      } else {
        String t = null;
        for (int i = 0; i < l; i++) {
          t = list.get(i);
          if (t != null && t.equals(param)) {
            return i;
          }
        }
      }
    }
    return -1;
  }

  /**查找整数型数组下标
   * @param list    待查找的数组
   * @param param   欲查找的元素
   * @return        下标.未找到返回-1
   */
  public static int listIndexOf(List<Integer> list, Integer param) {
    if (list != null) {
      int l = list.size();
      if (param == null) {
        for (int i = 0; i < l; i++) {
          if (list.get(i) == null) {
            return i;
          }
        }
      } else {
        Integer t = null;
        for (int i = 0; i < l; i++) {
          t = list.get(i);
          if (t != null && t.equals(param)) {
            return i;
          }
        }
      }
    }
    return -1;
  }

  /**判断元素是否在数组中
   * @param list  欲判断的数组 
   * @param param 欲判断的元素
   * @return      成功返回true
   */
  public static boolean listIncludes(List<String> list, String param) {
    return listIndexOf(list, param) >= 0;
  }

  /**判断元素是否在数组中
   * @param list  欲判断的数组 
   * @param param 欲判断的元素
   * @return      成功返回true
   */
  public static boolean listIncludes(List<Integer> list, Integer param) {
    return listIndexOf(list, param) >= 0;
  }

  /** 将long转换成int;超出返回-1
   * @param in    欲转换的long
   * @return      成功返回int;超出返回-1
   */
  public static int long2int(long in) {
    try {
      return Math.toIntExact(in);
    } catch (Exception e) {
    }
    return -1;
  }

  /** 取数据的字节集
   * @param obj      对象
   * @return         字节集
   */
  public static byte[] getBytes(Object obj) {
    if (obj != null) {
      if (obj instanceof Integer) {
        return ByteBuffer.allocate(Integer.BYTES).putInt((Integer) obj).array();
      } else if (obj instanceof Long) {
        return ByteBuffer.allocate(Long.BYTES).putLong((Long) obj).array();
      } else if (obj instanceof Float) {
        return ByteBuffer.allocate(Float.BYTES).putFloat((Float) obj).array();
      } else if (obj instanceof Double) {
        return ByteBuffer.allocate(Double.BYTES).putDouble((Double) obj).array();
      } else if (obj instanceof Boolean) {
        return new byte[] { (byte) (Boolean.TRUE.equals(obj) ? 1 : 0) };
      } else if (obj instanceof String) {
        return ((String) obj).getBytes();
      } else if (obj instanceof Byte[]) {
        return (byte[]) obj;
      } else if (obj instanceof Byte) {
        return new byte[] { (byte) obj };
      }
      try {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(obj);
        oos.flush();
        oos.close();
        return baos.toByteArray();
      } catch (Exception e) {
        utils.out(e);
      }
    }
    return null;
  }

  /** 取数据的哈希值
   * @param obj 数据
   * @return    哈希值
   */
  public static String toHash(Object obj) {
    return toHash(getBytes(obj), true);
  }

  /**取数据特征
   * @param obj     数据
   * @param isSha1  是否返回哈希值
   * @return        如果isSha1为false;则返回md5
   */
  public static String toHash(Object obj, boolean isSha1) {
    try {
      MessageDigest md = MessageDigest.getInstance(isSha1 ? "SHA-1" : "MD5");
      if (obj == null) {
        obj = sGetId();
      }
      md.update(getBytes(obj instanceof String ? obj : toJString(obj)));
      return String.format("%02X", new BigInteger(1, md.digest()));
    } catch (Exception e) {
      utils.out(e);
    }
    return "";
  }

  /** 将字节集转化为Hex字符串
   * @param b 要转化的字节
   * @return 转化后的Hex字符串
   */
  public static String byteToHex(byte b) {
    String hex = Integer.toHexString(b & 0xFF);
    if (hex.length() < 2) {
      hex = "0" + hex;
    }
    return hex;
  }

  /** 翻转字节集 */
  public static byte[] reverse(byte[] buffer) {
    int l = buffer.length, i = 0;
    byte[] ret = new byte[l];
    while (l-- > 0) {
      ret[i++] = buffer[l];
    }
    return ret;
  }

  /**取随机字节集
   * @param size  字节集长度
   * @return      随机字节集
   */
  public static byte[] randByte(int size) {
    byte[] r = new byte[size];
    Random rand = new Random(getId());
    for (int i = 0; i < size; i++) {
      r[i] = (byte) (rand.nextInt(0xff));
    }
    return r;
  }

  /**取随机字符串
   * @param size  字符串长度
   * @return      随机字符串
   */
  public static String randString(int size) {
    byte[] r = new byte[size];
    Random rand = new Random(getId());
    for (int i = 0; i < size; i++) {
      switch (rand.nextInt(3)) {
        case 0: // 数字
          r[i] = (byte) (rand.nextInt(9) + 48);
          break;
        case 1: // 大写字母
          r[i] = (byte) (rand.nextInt(25) + 65);
          break;
        case 2: // 小写字母
          r[i] = (byte) (rand.nextInt(25) + 97);
          break;

        default: // 全体字符/符号
          r[i] = (byte) (rand.nextInt(0x5e) + 0x20);
          break;
      }
    }
    try {
      return new String(r, "utf8");
    } catch (Exception e) {
      throw new RuntimeException("系统错误: 随机码");
    }
  }

  /**取随机数
   * @param max 最大值
   * @return    0-max的随机数
   */
  public static int rand(int max) {
    return new Random(getId()).nextInt(max);
  }

  /**取范围随机数
   * @param min 最小值
   * @param max 最大值
   * @return    min-max的随机数
   */
  public static int rand(int min, int max) {
    double random = Math.random() * 1000000000000000000L;
    DecimalFormat df = new DecimalFormat("0");
    return new Random(Long.valueOf(df.format(random))).nextInt((max - min) + 1) + min;
  }

  /** 转化byte[]为utf8字符串;失败返回null */
  public static String b2s(byte[] data) {
    try {
      return new String(data, "utf8");
    } catch (Exception e) {
    }
    return null;
  }

  /** 取request中的body */
  public static String getRequestBody(HttpServletRequest request) {
    try {
      BufferedReader reader = request.getReader();
      StringBuilder builder = new StringBuilder();
      String line;
      while ((line = reader.readLine()) != null) {
        builder.append(line);
      }
      reader.close();
      return builder.toString();
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  /** 将request中的请求内容转化为JSONObject */
  public static JSONObject request2json(HttpServletRequest request) {
    JSONObject ret = null;
    try {
      ret = JSONObject.parseObject(getRequestBody(request));
    } catch (Exception e) {
      ret = new JSONObject();
      Map<String, String[]> parameterMap = request.getParameterMap();
      for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
        ret.put(entry.getKey(), entry.getValue()[0]);
      }
    }
    return ret == null ? new JSONObject() : ret;
  }

  /** 将字符串转化成int */
  public static int s2i(String str) {
    if (str == null || str.length() == 0)
      return 0;
    char[] array = str.toCharArray();
    long result = 0; // 要返回的结果result
    int count = 0; // 记录‘+'或者‘-'出现的次数
    int num = 0; // 判断空格出现的位置
    int flag = 1; // 正数还是负数
    for (int i = 0; i < array.length; i++) {
      Character c = array[i];
      if (c >= '0' && c <= '9') {
        result = result * 10 + c - '0';
        // 判断是否溢出
        if (flag == 1 && result > Integer.MAX_VALUE) {
          return Integer.MAX_VALUE;
        } else if (flag == -1 && -result < Integer.MIN_VALUE)
          return Integer.MIN_VALUE;
        num++;
      } else if (c == ' ' && num == 0 && count == 0)
        continue;
      else if (c == '+' && count == 0) {
        count = 1;
      } else if (c == '-' && count == 0) {
        flag = -1;
        count = 1;
      } else {
        return (int) (flag * result);

      }
    }
    return (int) (flag * result);
  }

  /** 将任意类型转化为int 失败返回0 */
  public static int o2i(Object o) {
    int ret = 0;
    try {
      ret = Integer.valueOf(String.valueOf(o).trim());
    } catch (Exception e) {
    }
    return ret;
  }

  /** 将字符串转化成long */
  public static long s2l(String str) {
    if (str == null || str.length() == 0) {
      return 0;
    }
    char[] array = str.toCharArray();
    long result = 0; // 要返回的结果result
    long count = 0; // 记录‘+'或者‘-'出现的次数
    long num = 0; // 判断空格出现的位置
    long flag = 1; // 正数还是负数
    for (int i = 0; i < array.length; i++) {
      Character c = array[i];
      if (c >= '0' && c <= '9') {
        result = result * 10 + c - '0';
        // 判断是否溢出
        if (flag == 1 && result > Long.MAX_VALUE) {
          return Long.MAX_VALUE;
        } else if (flag == -1 && -result < Long.MIN_VALUE)
          return Long.MIN_VALUE;
        num++;
      } else if (c == ' ' && num == 0 && count == 0)
        continue;
      else if (c == '+' && count == 0) {
        count = 1;
      } else if (c == '-' && count == 0) {
        flag = -1;
        count = 1;
      } else {
        return (long) (flag * result);
      }
    }
    return (long) (flag * result);
  }

  /** 判断参数类型是否数字 */
  public static boolean isNumber(Object d) {
    String s = d.toString();
    if ((s.indexOf("'") == 0 && s.indexOf("'", 1) == s.length() - 1)
        || (s.indexOf("\"") == 0 && s.indexOf("\"", 1) == s.length() - 1)) {
      s = s.substring(1, s.length() - 1);
    }
    int bit;
    if (s.indexOf("0x") == 0) {
      bit = 16;
      s = s.substring(2);
    } else {
      bit = 10;
    }
    while (s.length() > 1 && s.indexOf("0") == 0) {
      s = s.substring(1);
    }
    try {
      return s.equals(new BigInteger(s).toString(bit));
    } catch (Exception e) {
      return false;
    }
  }

  /**分割字符串;
   * @param s 欲分割的字符串
   * @param k 分割标志
   * @return  将s以k作为分隔符,分割后的数组
   */
  public static List<String> split(String s, String k) {
    if (s == null || k == null || s.length() < k.length()) {
      return null;
    }
    List<String> ret = new ArrayList<>();
    int i = s.indexOf(k), l = 0, kl = k.length();
    if (i < 0) {
      ret.add(s);
    } else {
      do {
        ret.add(s.substring(l, i));
        l = i + kl;
        i = s.indexOf(k, l);
      } while (i > 0);
      ret.add(s.substring(l));
    }
    return ret;
  }

  /**将字符串以9级压缩成byte[]
   * @param input 欲压缩的字符串
   * @return      压缩后的数据
   */
  public static byte[] zip(String input) {
    return zip(input, 9);
  }

  /**将字符串压缩成byte[]
   * @param input 欲压缩的字符串
   * @param level 压缩等级;默认9
   * @return      压缩后的数据
   */
  public static byte[] zip(String input, int level) {
    try {
      Deflater deflater = new Deflater(level);
      deflater.setInput(input.getBytes("UTF-8"));
      deflater.finish();

      ByteArrayOutputStream outputStream = new ByteArrayOutputStream(input.length());
      byte[] buffer = new byte[4096];
      while (!deflater.finished()) {
        int count = deflater.deflate(buffer); // Compresses
        outputStream.write(buffer, 0, count);
      }
      outputStream.close();
      byte[] output = outputStream.toByteArray();
      deflater.end();
      return output;
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  /**解压数据
   * @param input 待解压的数据
   * @return      解压后的数据
   */
  public static byte[] unzip(byte[] input) {
    try {
      Inflater inflater = new Inflater();
      inflater.setInput(input);

      // 使用ByteArrayInputStream和InflaterInputStream来解压缩数据
      InflaterInputStream inputStream = new InflaterInputStream(new ByteArrayInputStream(input), inflater);
      ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

      byte[] buffer = new byte[1024];
      int len;
      while ((len = inputStream.read(buffer)) != -1) {
        outputStream.write(buffer, 0, len);
      }

      // 关闭流
      inputStream.close();
      outputStream.close();
      return outputStream.toByteArray();
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  /**解压数据为字符串
   * @param input 待解压的数据
   * @return      解压后的数据
   */
  public static String sunzip(byte[] input) {
    try {
      Inflater inflater = new Inflater();
      inflater.setInput(input);

      // 使用ByteArrayInputStream和InflaterInputStream来解压缩数据
      InflaterInputStream inputStream = new InflaterInputStream(new ByteArrayInputStream(input), inflater);
      InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);

      StringBuilder decompressedStringBuilder = new StringBuilder();
      char[] buffer = new char[1024];
      int len;
      while ((len = reader.read(buffer)) != -1) {
        decompressedStringBuilder.append(buffer, 0, len);
      }

      // 关闭流
      reader.close();
      inputStream.close();

      return decompressedStringBuilder.toString();
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  /**根据大写字母分割驼峰式字符串。
   * @param input 驼峰式字符串
   * @return 分割后的单词列表
   */
  public static List<String> splitByUpperCase(String input) {
    List<String> result = new ArrayList<>();
    StringBuilder currentWord = new StringBuilder();
    for (char ch : input.toCharArray()) {
      if (Character.isUpperCase(ch)) {
        if (currentWord.length() > 0) {
          result.add(currentWord.toString());
          currentWord.setLength(0);
        }
      }
      currentWord.append(ch);
    }
    // 添加最后一个单词（如果有的话）
    if (currentWord.length() > 0) {
      result.add(currentWord.toString());
    }
    return result;
  }

  /** 驼峰转下划线格式 */
  public static String Hump2Underline(String param) {
    return param.replaceAll("([A-Z])", "_$1").toLowerCase();
  }

  /** 驼峰化字符串 */
  public static String UnderlineHump(String in) {
    return UnderlineHump(in, false);
  }

  /**驼峰化字符串
   * @param in          欲转化的字符串
   * @param fristUpper  首字母是否大写
   * @return            驼峰化的字符串
   */
  public static String UnderlineHump(String in, Boolean fristUpper) {
    String r = in;
    if (in != null) {
      // int i, l = r.length();
      // while ((i = r.indexOf("_")) >= 0 && i < --l) {
      // r = r.substring(0, i) + r.substring(++i, ++i).toUpperCase() + (l >= i ?
      // r.substring(i) : "");
      // }
      // r = r.substring(0, 1).toLowerCase() + r.substring(1);
      java.util.regex.Matcher m = java.util.regex.Pattern.compile("[_\\-]+(\\w)").matcher(r);
      StringBuffer sb = new StringBuffer();
      while (m.find()) {
        m.appendReplacement(sb, m.group(1).toUpperCase());
      }
      if (sb.length() > 0) {
        char c = sb.charAt(0);
        if (fristUpper != null && fristUpper) {
          if (c >= 'a' && c <= 'z') {
            c -= 32;
          }
        } else {
          if (c >= 'A' && c <= 'Z') {
            c += 32;
          }
        }
        sb.setCharAt(0, c); // 首字母 大小写转换
        m.appendTail(sb);
        r = sb.toString();
      }
    }
    return r;
  }

  /** 首字母小写 */
  public static String FristLower(String in) {
    String r = "";
    if (in != null) {
      StringBuffer sb = new StringBuffer(in);
      char c = sb.charAt(0);
      if (c >= 'A' && c <= 'Z') {
        sb.setCharAt(0, (char) (c + 32));
      }
      r = sb.toString();
    }
    return r;
  }

  /**静态类转化成JSONObject(属性名是类的小驼峰属性名,值为该值对应的数据值)
   * @param <T>   类型
   * @param clazz 实体类型
   * @return  {小驼峰属性名:对应值,...}
   */
  public static <T> JSONObject StaticClassToJsonString(Class<T> clazz) {
    JSONObject r = new JSONObject();
    String n;
    for (Field field : clazz.getDeclaredFields()) {
      n = field.getName();
      try {
        r.put(UnderlineHump(n), field.get(n));
      } catch (Exception e) {
      }
    }
    return r;
  }

  /**将参数中的"#entity"字段转化为 java数据;如果没有#entity字段.则将参数本身进行转化
   * @param <T>   欲转化的类型
   * @param p     包含#entity字段的数据
   * @param clazz 转化的类型
   * @return      转化后的数据
   */
  public static <T> T getEntity(JSONObject p, Class<T> clazz) {
    // return p.containsKey("#entity") ?
    // p.getJSONObject("#entity").toJavaObject(clazz) : p.toJavaObject(clazz);
    return p.containsKey("#entity") ? toJavaObject(p.getJSONObject("#entity"), clazz)
        : toJavaObject(p, clazz);
  }

  /**将参数中的"#entity"字段转化为 java数据;如果没有#entity字段.则将参数本身进行转化
   * @param <T>   欲转化的类型
   * @param p     包含#entity字段的数据
   * @param clazz 转化的类型
   * @param cid   转化后,设置转化后数据当中的 create为此值
   * @return      转化后的数据
   */
  public static <T> T getEntity(JSONObject p, Class<T> clazz, String cid) {
    T obj = getEntity(p, clazz);
    if (obj != null && cid != null) {
      try {
        Field field = clazz.getDeclaredField("create");
        field.setAccessible(true); // 如果字段是私有的，需要设置可访问
        if (field.getType().equals(String.class)) {
          field.set(obj, cid);
        }
      } catch (Exception e) {
      }
    }
    return obj;
  }

  /**获取私有属性值
   * @param s 要获取私有属性的数据实体
   * @param n 属性名
   * @return  获取到的值
   */
  public static Object getPrivate(Object s, String n) {
    Class<?> cls = s.getClass();
    try {
      Field field = cls.getDeclaredField(n);
      field.setAccessible(true);
      return field.get(s);
    } catch (Exception e) {
      // 获取属性错误
      System.out.println("getPrivate:获取属性错误");
    }

    return null;
  }

  /**获取私有属性值
   * @param s 要获取私有属性的数据实体
   * @param n 属性名数组; 如果便利时,其中一个值为null则中断返回null;
   * @return  最后一次获取到的值
   */
  public static Object getPrivate(Object s, String[] n) {
    Object ret = s;
    for (String nd : n) {
      ret = getPrivate(ret, nd);
      if (ret == null) {
        break;
      }
    }

    return ret;
  }
}
